import java.io.*;
import java.net.*;

public class SyncUDPSocket { //Synchronized UDP wrapper
	private DatagramSocket _socket = null; //UDP socket
	private UDPReader _udpReader = null;
	private UDPWriter _udpWriter = null;
	
	private class UDPReader {
		/**
		 * Gets a response packet from the socket
		 * @param packet
		 * @throws IOException
		 */
		public void receive(DatagramPacket packet) throws IOException{
			
			synchronized (this) {
				_socket.receive(packet);
			}
			
		}
	}
	
	private class UDPWriter {
		public void send(DatagramPacket packet) throws IOException{
			
			synchronized (this) {
				_socket.send(packet);
			}
		}
	}
	
	/**
	 * Constructor
	 * @param port - port of communication
	 * @throws SocketException
	 */
	public SyncUDPSocket(int port) throws SocketException{
		_socket = new DatagramSocket(port);
		_udpReader = new UDPReader();
		_udpWriter = new UDPWriter();
	}
	
	/**
	 * Sets the timeout
	 * @param timeout
	 * @throws SocketException
	 */
	public synchronized void setSoTimeout(int timeout) throws SocketException{
		_socket.setSoTimeout(timeout);
	}
	
	/**
	 * Close the socket
	 */
	public synchronized void close() {
		_socket.close();
	} 
	
	/**
	 * Sends a packet
	 * @param packet
	 * @throws IOException
	 */
	public void send(DatagramPacket packet) throws IOException{
		_udpWriter.send(packet);
	}
	
	/**
	 * Gets InetAddress of the socket
	 * @return
	 */
	public InetAddress getInetAddress() {
		return _socket.getInetAddress(); 
	}
	
	/**
	 * Gets a response packet from the socket
	 * @param packet
	 * @throws IOException
	 */
	public void receive(DatagramPacket packet) throws IOException{
		_udpReader.receive(packet);
	}

	/**
	 * Gets whether the connection is alive
	 * @return
	 */
	public boolean isAlive() {return true;} 

	/**
	 * Gets local address
	 * @return 
	 */
	public InetAddress getLocalAddress() {
		return _socket.getLocalAddress();
	}
	
	/**
	 * Gets local port
	 * @return
	 */
	public int getLocalPort() {
		return _socket.getLocalPort();
	}
}
